﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using WcfContrib.Utils;
using System.Threading;
using WcfContrib.Configuration;
using WcfContrib.Resources;

namespace WcfContrib.Extensions.Caching
{
    /// <summary>
    /// Represents the output cache controller used for output caching
    /// The controller initializes the cache provider using the factory
    /// Make sure you dispose it in your process exit point if you are using output caching
    /// </summary>
    public class OutputCacheController : IDisposable
    {
        static readonly Type DefaultFactoryType = typeof(IntervalBasedCacheProviderFactory);

        static readonly OutputCacheController _controller = new OutputCacheController();
        /// <summary>
        /// Gets the current singleton controller.
        /// </summary>
        /// <value>The current singleton controller.</value>
        public static OutputCacheController Current
        {
            get { return _controller; }
        }

        IOutputCacheProviderFactory _factory;

        /// <summary>
        /// Gets the type of the provider factory.
        /// </summary>
        /// <value>The type of the provider factory.</value>
        public Type ProviderFactoryType { get; private set; }
        /// <summary>
        /// Gets the output cache provider.
        /// </summary>
        /// <value>The provider.</value>
        public IOutputCacheProvider Provider { get; private set; }

        OutputCacheController()
        {
            string typeName = WcfContribConfigurationSection.GetSection().Extensions.OutputCache.ProviderFactoryTypeName;
            if (!string.IsNullOrEmpty(typeName))
            {
                try
                {
                    ProviderFactoryType = Type.GetType(typeName, true);
                }
                catch (Exception ex)
                {
                    throw new ArgumentException(ExceptionMessages.OutputCache_ProviderFactoryTypeNameInvalid, "ProviderFactoryTypeName", ex);
                }
            }
            else
            {
                ProviderFactoryType = DefaultFactoryType;
            }

            InitProvider();
        }

        void InitProvider()
        {
            if (_factory == null)
            {
                _factory = (IOutputCacheProviderFactory)Activator.CreateInstance(ProviderFactoryType);
            }

            Provider = _factory.CreateProvider();
        }

        #region IDisposable Members

        /// <summary>
        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
        /// </summary>
        public void Dispose()
        {
            if (Provider != null)
            {
                using (Provider as IDisposable) { };
                Provider = null;
            }
        }

        #endregion
    }
}
